/*************************************************
** 版权所有:  PUBLIC Copyright (c) 2019-2029
** 内容摘要:  串口1到串口6发送DMA程序
** 当前版本:  v1.1
** 作    者:  lixiaobin1996@163.com
** 完成日期:  2022.01.10
**************************************************/

#include "sys.h"
#include "delay.h"
#include "usart6.h"
#include "string.h"

static char usart6_dma_tx[256];
unsigned char usart6_tx_busy_flag = 0;

static void usart6_gpio_init(void)  
{  
	GPIO_InitTypeDef GPIO_InitStructure;  

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; 
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);  
	GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);  	
}

static void usart6_usart_init(unsigned int bauderate, unsigned short wordLength, unsigned short stopBits, unsigned short Parity)
{
	USART_InitTypeDef USART_InitStructure;  

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
	
	USART_InitStructure.USART_BaudRate = bauderate;
	USART_InitStructure.USART_WordLength = wordLength;  
	USART_InitStructure.USART_StopBits = stopBits;  
	USART_InitStructure.USART_Parity = Parity;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 

	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  

	USART_Init(USART6, &USART_InitStructure);  
	USART_Cmd(USART6, ENABLE);

	USART_ITConfig(USART6, USART_IT_RXNE, ENABLE);
	USART_ITConfig(USART6, USART_IT_IDLE, ENABLE);
}

static void usart6_dma_init(void)  
{  
	DMA_InitTypeDef  DMA_InitStructure;  

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
	
	DMA_DeInit(DMA2_Stream6);		
	DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;   
	DMA_InitStructure.DMA_BufferSize = 256;   
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  
	DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;  
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;  
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;  
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;  
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 

	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART6->DR; 	
	DMA_InitStructure.DMA_Channel = DMA_Channel_5; 
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)usart6_dma_tx; 	

	DMA_Init(DMA2_Stream6, &DMA_InitStructure); 		
	DMA_ITConfig(DMA2_Stream6, DMA_IT_TC, ENABLE);
}

static void usart6_nvic_init(void)  
{  
	NVIC_InitTypeDef NVIC_InitStructure;   

	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;  
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

	NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream6_IRQn; 
	NVIC_Init(&NVIC_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;
	NVIC_Init(&NVIC_InitStructure);	
}  

void usart6_init(unsigned int bauderate, unsigned short wordLength, unsigned short stopBits, unsigned short Parity)
{
	usart6_nvic_init();
	usart6_gpio_init();
	usart6_usart_init(bauderate, wordLength, stopBits, Parity);
	usart6_dma_init();
}

void usart6_send(char *buf, unsigned char len)
{
	while(usart6_tx_busy_flag)	delay_ms(2);
	usart6_tx_busy_flag = 1;

	memcpy(usart6_dma_tx, buf, len);
	DMA_SetCurrDataCounter(DMA2_Stream6, len);
	DMA_Cmd(DMA2_Stream6, ENABLE);                
	USART_DMACmd(USART6, USART_DMAReq_Tx, ENABLE);
}

/*****************USART6  TX******************/
void DMA2_Stream6_IRQHandler(void)  
{
	/* Test on DMA Stream Transfer Complete interrupt */  
	if (DMA_GetITStatus(DMA2_Stream6, DMA_IT_TCIF6))  
	{  
		/* Clear DMA Stream Transfer Complete interrupt pending bit */  
		DMA_ClearITPendingBit(DMA2_Stream6, DMA_IT_TCIF6); 
		USART_DMACmd(USART6, USART_DMAReq_Tx, DISABLE);        
		DMA_Cmd(DMA2_Stream6, DISABLE);  	

		usart6_tx_busy_flag = 1;	
	}
}

/*****************USART6  RX******************/
void USART6_IRQHandler(void)
{	
	/* USART in mode Sender   --------------------------------------------------*/
	if(USART_GetITStatus(USART6, USART_IT_TXE) == SET)
	{
		USART_ClearITPendingBit(USART6, USART_IT_TXE);
	}
	
	/* USART Receive Complete */
	if(USART_GetITStatus(USART6, USART_IT_IDLE) == SET)
	{
		USART_ClearITPendingBit(USART6, USART_IT_IDLE);	
	}
	
	/* USART in mode Receiver --------------------------------------------------*/
	if(USART_GetITStatus(USART6, USART_IT_RXNE) == SET)
	{
		USART_ClearITPendingBit(USART6, USART_IT_RXNE);
		USART_ReceiveData(USART6);				
	} 	
}

